package com.example.myhl7project;

import ca.uhn.hl7v2.DefaultHapiContext;
import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.Version;
import ca.uhn.hl7v2.model.GenericMessage;
import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.model.v26.message.ACK;
import ca.uhn.hl7v2.parser.PipeParser;
import ca.uhn.hl7v2.util.Terser;
import org.apache.camel.Exchange;
import org.apache.camel.LoggingLevel;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.hl7.HL7DataFormat;
import org.apache.camel.component.mllp.MllpException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class MyMllpRouter extends RouteBuilder {
    private final HL7Processor hl7Processor;
    private final HL7MessageService hl7MessageService;

    public MyMllpRouter(HL7Processor hl7Processor, HL7MessageService hl7MessageService) {
        this.hl7Processor = hl7Processor;
        this.hl7MessageService = hl7MessageService;
    }

    @Value("${hl7.server.port:8088}")
    private int hl7Port;

    @Override
    public void configure() {
        // 创建 PipeParser 并禁用验证
        PipeParser pipeParser = new PipeParser();
        pipeParser.getParserConfiguration().setValidating(false); // 关键！禁用验证

        // 配置 HL7DataFormat 使用非验证的 Parser
        HL7DataFormat hl7 = new HL7DataFormat();
        hl7.setParser(pipeParser);  // 使用自定义的 PipeParser

        // 异常处理
        onException(MllpException.class, HL7Exception.class)
                .log(LoggingLevel.ERROR, "HL7 Processing Error: ${exception.message}")
                .handled(true)
                .process(this::generateErrorAck);

       /* onException(Exception.class)
                .log(LoggingLevel.ERROR, "Unexpected Error: ${exception.message}")
                .handled(true)
                .process(this::generateErrorAck);*/

        fromF("mllp://0.0.0.0:%d?autoAck=true&validatePayload=false", hl7Port)
                .routeId("blt-hl7-server")
                .log("✅ Received HL7 message from ${header.CamelMllpRemoteAddress}")

                // 1. 解组 HL7 消息为原始 Message 类型
                .unmarshal(hl7)

                // 2. 强制转换为 GenericMessage（关键步骤）
                .process(exchange -> {
                    Message original = exchange.getMessage().getBody(Message.class);

                    DefaultHapiContext context = new DefaultHapiContext();
                    context.getParserConfiguration().setValidating(false);


                    Message genericMessage = context.newMessage("ORU", "R01", Version.V26);
                    genericMessage.parse(original.encode());

                    exchange.getMessage().setBody(genericMessage);
                })

                // 3. 预处理：记录原始消息并验证基本结构
                .process(hl7Processor)

                // 4. 处理业务逻辑
                .bean(hl7MessageService, "processMessage")

                // 5. 生成 ACK
                .process(exchange -> {
                    Message received = exchange.getMessage().getBody(Message.class);
                    ACK ack = (ACK) received.generateACK();
                    exchange.getMessage().setBody(ack);
                })

                // 6. 返回 ACK
                .marshal(hl7)
                .log("🚀 Sent ACK response");
    }

    private void generateErrorAck(Exchange exchange) {
        Exception cause = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);
        String originalMessage = exchange.getIn().getBody(String.class);

        try {
            String controlId = extractControlId(originalMessage);
            String ackMsg = "MSH|^~\\&|||||||ACK||P|2.6\r\n" +
                    "MSA|AE|" + controlId + "|Error: " +
                    cause.getMessage().substring(0, Math.min(80, cause.getMessage().length()));
            exchange.getMessage().setBody(ackMsg);
        } catch (Exception e) {
            exchange.getMessage().setBody("MSH|^~\\&|||||||ACK||P|2.6\r\nMSA|AE||Processing Error");
        }
    }

    private String extractControlId(String hl7Message) {
        if (hl7Message != null && hl7Message.startsWith("MSH")) {
            String[] segments = hl7Message.split("\r");
            for (String segment : segments) {
                if (segment.startsWith("MSH")) {
                    String[] fields = segment.split("\\|");
                    if (fields.length > 9) {
                        return fields[9];
                    }
                }
            }
        }
        return "";
    }
}
